package de.sendorian.util.io;


import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLConnection;

import javax.imageio.ImageIO;

import org.apache.log4j.Logger;
import org.htmlparser.http.ConnectionManager;
import org.htmlparser.util.ParserException;

public class FileReader {

	private static final Logger logger = Logger.getLogger(FileReader.class.getName());

	private ConnectionManager connectionManager = new ConnectionManager();


	public byte[] getFile(String url) throws IOException {
		return getFile(getInputStream(url));
	}


	public byte[] getFile(InputStream in) throws IOException {
		long start = System.currentTimeMillis();
		byte[] out = new byte[0];

		try {
			in = new BufferedInputStream(in);
			// read 64 kb at once
			int bufLen = 64 * 1024;
			byte[] buf = new byte[bufLen];
			byte[] tmp = null;
			int len = 0;
			while ((len = in.read(buf, 0, bufLen)) != -1) {
				// extend array
				tmp = new byte[out.length + len];
				// copy data
				System.arraycopy(out, 0, tmp, 0, out.length);
				System.arraycopy(buf, 0, tmp, out.length, len);
				out = tmp;
				tmp = null;
			}
			logger.debug("   Time for Saving file: " + (System.currentTimeMillis() - start)
			    + " [ms]");
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (Exception e) {
				}
			}
		}

		return out;
	}


	/**
	 * Directly saves a file specified by a given URL to a file whithout storing it in memory.
	 */
	public boolean save(String url, String dir, String fileName) throws IOException {
		File file = new File(dir, fileName);
		if (file.exists()) {
			logger.info("The file \"" + dir + java.io.File.separator + fileName
			    + "\" already exists. Skipping.");
			return false;
		}
		return save(getInputStream(url), file, dir);
	}


	/**
	 * Directly saves a file specified by a given URL to a file whithout storing it in memory.
	 */
	public boolean save(InputStream in, String dir, String fileName) throws IOException {
		File file = new File(dir, fileName);
		if (file.exists()) {
			logger.info("The file \"" + dir + java.io.File.separator + fileName
			    + "\" already exists. Skipping.");
			return false;
		}
		return save(in, file, dir);
	}


	private boolean save(InputStream in, File file, String dir) throws IOException {
		new FileWriter().createDir(dir);
		file.createNewFile();

		OutputStream out = new BufferedOutputStream(new FileOutputStream(file), 64 * 1024);
		// read 64 kb at once
		in = new BufferedInputStream(in, 64 * 1024);

		try {
			int readByte = -1;
			while ((readByte = in.read()) != -1) {
				out.write(readByte);
			}
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (Exception e) {
				}
			}
			if (out != null) {
				try {
					out.flush();
					out.close();
				} catch (Exception e) {
				}
			}
		}
		return true;
	}


	public BufferedImage getImage(String url) throws IOException {
		InputStream in = getInputStream(url);
		return ImageIO.read(in);
	}


	private InputStream getInputStream(String url) throws IOException {
		URLConnection connection = null;
		try {
			connection = connectionManager.openConnection(url);
		} catch (ParserException e) {
			String message = "Could not open connection to '" + url + "'";
			logger.error(message);
			throw new IOException(message);
		}

		connection.connect();
		return connection.getInputStream();
	}

}
